package com.haoniu.common.utils.huanxin.comm;

import com.haoniu.common.config.Global;
import com.haoniu.common.utils.YamlUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

public class ClientContext {
	
	/**
	 * Configuration Source Type
	 */
	public static final String INIT_FROM_PROPERTIES = "FILE";
	
	public static final String INIT_FROM_CLASS = "CLASS";
	
	/**
	 * Implementation List
	 */
	public static final String JERSEY_API = "jersey";
	
	public static final String HTTPCLIENT_API = "httpclient";
	
	/**
	 * Properties
	 */
	private static final String API_PROTOCAL_KEY = "huanxin.protocal";
	
	private static final String API_HOST_KEY = "huanxin.host";
	
	private static final String API_ORG_KEY = "huanxin.org";
	
	private static final String API_APP_KEY = "huanxin.app";
	
	private static final String APP_CLIENT_ID_KEY = "huanxin.clientId";
	
	private static final String APP_CLIENT_SECRET_KEY = "huanxin.clientSecret";
	
	private static final String APP_IMP_LIB_KEY = "huanxin.impLib";
	
	private static final Logger log = LoggerFactory.getLogger(ClientContext.class);
	
	private static ClientContext context;
		
	private Boolean initialized = Boolean.FALSE;
	
	private String protocal;
	
	private String host;
	
	private String org;
	
	private String app;
	
	private String clientId;
	
	private String clientSecret;
	
	private String impLib;
	
	private EasemobRestAPIFactory factory;
	/**
	 * Wrap the token generator
	 */
	private TokenGenerator token;
	
	private ClientContext() {};
	
	public static ClientContext getInstance() {
		if( null == context ) {
			context = new ClientContext();
		}
		
		return context;
	}
	
	public ClientContext init(String type) {
		if( initialized ) {
			log.warn("Context has been initialized already, skipped!");
			return context;
		}
		
		if( StringUtils.isBlank(type) ) {
			log.warn("Context initialization type was set to FILE by default.");
			type = INIT_FROM_PROPERTIES;
		}
		
		if( INIT_FROM_PROPERTIES.equals(type) ) {
			initFromPropertiesFile();
		} 
		else if( INIT_FROM_CLASS.equals(type) ){
			initFromStaticClass();
		} 
		else {
			log.error(MessageTemplate.print(MessageTemplate.UNKNOW_TYPE_MSG, new String[]{type, "context initialization"}));
			return context;
		}
		
		if( context.initialized ) {
			token = new TokenGenerator(context);
		}
		
		return context;
	}
	
	public EasemobRestAPIFactory getAPIFactory() {
		if( !context.isInitialized() ) {
			log.error(MessageTemplate.INVAILID_CONTEXT_MSG);
			throw new RuntimeException(MessageTemplate.INVAILID_CONTEXT_MSG);
		}
		
		if( null == this.factory ) {
			this.factory = EasemobRestAPIFactory.getInstance(context);
		}
		
		return this.factory;
	}
	
	public String getSeriveURL() {
		if (null == context || !context.isInitialized()) {
			log.error(MessageTemplate.INVAILID_CONTEXT_MSG);
			throw new RuntimeException(MessageTemplate.INVAILID_CONTEXT_MSG);
		}

		String serviceURL = context.getProtocal() + "://" + context.getHost() + "/" + context.getOrg() + "/" + context.getApp();

		return serviceURL;
	}
	
	public String getAuthToken() {
		if( null == token ) {
			log.error(MessageTemplate.INVAILID_TOKEN_MSG);
			throw new RuntimeException(MessageTemplate.INVAILID_TOKEN_MSG);
		}
		
		return token.request(Boolean.FALSE);
	}

	private static String ENV = "dev";

	private void initFromPropertiesFile() {

		ENV = Global.getConfig("spring.profiles.active");
		Map<?, ?> yamlMap = null;
		try {
			yamlMap = YamlUtil.loadYaml("application-" + ENV + ".yml");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		String protocal =  String.valueOf(YamlUtil.getProperty(yamlMap, API_PROTOCAL_KEY));
		String host =  String.valueOf(YamlUtil.getProperty(yamlMap, API_HOST_KEY));
		String org =  String.valueOf(YamlUtil.getProperty(yamlMap, API_ORG_KEY));
		String app =  String.valueOf(YamlUtil.getProperty(yamlMap, API_APP_KEY));
		String clientId =  String.valueOf(YamlUtil.getProperty(yamlMap, APP_CLIENT_ID_KEY));
		String clientSecret =  String.valueOf(YamlUtil.getProperty(yamlMap, APP_CLIENT_SECRET_KEY));
		String impLib =  String.valueOf(YamlUtil.getProperty(yamlMap, APP_IMP_LIB_KEY));

		if( StringUtils.isBlank(protocal) || StringUtils.isBlank(host) || StringUtils.isBlank(org) || StringUtils.isBlank(app) || StringUtils.isBlank(clientId) || StringUtils.isBlank(clientSecret) || StringUtils.isBlank(impLib) ) {
			log.error(MessageTemplate.print(MessageTemplate.INVAILID_PROPERTIES_MSG, new String[]{"config.properties"}));
			return; // Context not initialized
		}
		
		context.protocal = protocal;
		context.host = host;
		context.org = org;
		context.app = app;
		context.clientId = clientId;
		context.clientSecret = clientSecret;
		context.impLib = impLib;
		
		log.debug("protocal: " + context.protocal);
		log.debug("host: " + context.host);
		log.debug("org: " + context.org);
		log.debug("app: " + context.app);
		log.debug("clientId: " + context.clientId);
		log.debug("clientSecret: " + context.clientSecret);
		log.debug("impLib: " + context.impLib);
		
		initialized = Boolean.TRUE;
	}
	
	private ClientContext initFromStaticClass() {
		// TODO
		return null;
	}

	public String getProtocal() {
		return protocal;
	}

	public String getHost() {
		return host;
	}

	public String getOrg() {
		return org;
	}

	public String getApp() {
		return app;
	}

	public String getClientId() {
		return clientId;
	}

	public String getClientSecret() {
		return clientSecret;
	}
	
	public Boolean isInitialized() {
		return initialized;
	}
	
	public String getImpLib() {
		return impLib;
	}
	
	public static void main(String[] args) {
		ClientContext.getInstance().init(null);
	}
	
}
